package com.lib.utils;

import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.CallLog;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.io.File;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * <pre>
 *     author: Blankj
 *     blog  : http://blankj.com
 *     time  : 2016/8/2
 *     desc  : 手机相关工具类
 * </pre>
 */
@SuppressLint({"MissingPermission"})
public class PhoneUtils {
    private PhoneUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    /**
     * 判断设备是否是手机
     *
     * @param context 上下文
     * @return {@code true}: 是<br>{@code false}: 否
     */
    public static boolean isPhone(Context context) {

        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return tm != null && tm.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
    }

    /**
     * 获取IMIE码
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.READ_PHONE_STATE"/>}</p>
     *
     * @param context 上下文
     * @return IMIE码
     */
    @SuppressLint("HardwareIds")
    public static String getIMEI(Context context) {
        String str = "";
        try {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            str = tm.getDeviceId();
        } catch (Exception ignored) {
        }
        return str;
    }

    /**
     * 获取IMSI码
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.READ_PHONE_STATE"/>}</p>
     *
     * @param context 上下文
     * @return IMIE码
     */
    @SuppressLint("HardwareIds")
    public static String getIMSI(Context context) {
        String str = "";
        try {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            str = tm != null ? tm.getSubscriberId() : "";
        } catch (Exception ignored) {
        }
        return str;
    }

    /**
     * 获取移动终端类型
     *
     * @param context 上下文
     * @return 手机制式
     * <ul>
     * <li>{@link TelephonyManager#PHONE_TYPE_NONE } : 0 手机制式未知</li>
     * <li>{@link TelephonyManager#PHONE_TYPE_GSM  } : 1 手机制式为GSM，移动和联通</li>
     * <li>{@link TelephonyManager#PHONE_TYPE_CDMA } : 2 手机制式为CDMA，电信</li>
     * <li>{@link TelephonyManager#PHONE_TYPE_SIP  } : 3</li>
     * </ul>
     */
    public static int getPhoneType(Context context) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return tm != null ? tm.getPhoneType() : -1;
    }

    /**
     * 获取Sim卡运营商名称
     * <p>中国移动、如中国联通、中国电信</p>
     *
     * @param context 上下文
     * @return sim卡运营商名称
     */
    public static String getSimOperatorName(Context context) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return tm != null ? tm.getSimOperatorName() : null;
    }

    /**
     * 获取Sim卡运营商名称
     * <p>中国移动、如中国联通、中国电信</p>
     *
     * @param context 上下文
     * @return 移动网络运营商名称
     */
    public static String getSimOperatorByMnc(Context context) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        String operator = tm != null ? tm.getSimOperator() : null;
        if (operator == null)
            return null;
        switch (operator) {
            case "46000":
            case "46002":
            case "46007":
                return "中国移动";
            case "46001":
                return "中国联通";
            case "46003":
                return "中国电信";
            default:
                return operator;
        }
    }

    /**
     * 获取手机状态信息
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.READ_PHONE_STATE"/>}</p>
     *
     * @param context 上下文
     * @return DeviceId(IMEI) = 99000311726612<br>
     * DeviceSoftwareVersion = 00<br>
     * Line1Number =<br>
     * NetworkCountryIso = cn<br>
     * NetworkOperator = 46003<br>
     * NetworkOperatorName = 中国电信<br>
     * NetworkType = 6<br>
     * honeType = 2<br>
     * SimCountryIso = cn<br>
     * SimOperator = 46003<br>
     * SimOperatorName = 中国电信<br>
     * SimSerialNumber = 89860315045710604022<br>
     * SimState = 5<br>
     * SubscriberId(IMSI) = 460030419724900<br>
     * VoiceMailNumber = *86<br>
     */
    @SuppressLint("HardwareIds")
    public static String getPhoneStatus(Context context) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        String str = "";
        str += "DeviceId(IMEI) = " + tm.getDeviceId() + "\n";
        str += "DeviceSoftwareVersion = " + tm.getDeviceSoftwareVersion() + "\n";
        str += "Line1Number = " + tm.getLine1Number() + "\n";
        str += "NetworkCountryIso = " + tm.getNetworkCountryIso() + "\n";
        str += "NetworkOperator = " + tm.getNetworkOperator() + "\n";
        str += "NetworkOperatorName = " + tm.getNetworkOperatorName() + "\n";
        str += "NetworkType = " + tm.getNetworkType() + "\n";
        str += "honeType = " + tm.getPhoneType() + "\n";
        str += "SimCountryIso = " + tm.getSimCountryIso() + "\n";
        str += "SimOperator = " + tm.getSimOperator() + "\n";
        str += "SimOperatorName = " + tm.getSimOperatorName() + "\n";
        str += "SimSerialNumber = " + tm.getSimSerialNumber() + "\n";
        str += "SimState = " + tm.getSimState() + "\n";
        str += "SubscriberId(IMSI) = " + tm.getSubscriberId() + "\n";
        str += "VoiceMailNumber = " + tm.getVoiceMailNumber() + "\n";
        return str;
    }

    /**
     * 跳至拨号界面
     *
     * @param context     上下文
     * @param phoneNumber 电话号码
     */
    public static void dial(Context context, String phoneNumber) {
        context.startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber)));
    }

    /**
     * 拨打电话
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.CALL_PHONE"/>}</p>
     *
     * @param context     上下文
     * @param phoneNumber 电话号码
     */
    public static void call(Context context, String phoneNumber) {
        context.startActivity(new Intent("android.intent.action.CALL", Uri.parse("tel:" + phoneNumber)));
    }

    /**
     * 跳至发送短信界面
     *
     * @param context     上下文
     * @param phoneNumber 接收号码
     * @param content     短信内容
     */
    public static void sendSms(Context context, String phoneNumber, String content) {
        Uri uri = Uri.parse("smsto:" + (TextUtils.isEmpty(phoneNumber) ? "" : phoneNumber));
        Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
        intent.putExtra("sms_body", TextUtils.isEmpty(content) ? "" : content);
        context.startActivity(intent);
    }

    /**
     * 发送短信
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.SEND_SMS"/>}</p>
     *
     * @param context     上下文
     * @param phoneNumber 接收号码
     * @param content     短信内容
     */
    public static void sendSmsSilent(Context context, String phoneNumber, String content) {
        if (TextUtils.isEmpty(content)) {
            return;
        }
        PendingIntent sentIntent = PendingIntent.getBroadcast(context, 0, new Intent(), 0);
        SmsManager smsManager = SmsManager.getDefault();
        if (content.length() >= 70) {
            List<String> ms = smsManager.divideMessage(content);
            for (String str : ms) {
                smsManager.sendTextMessage(phoneNumber, null, str, sentIntent, null);
            }
        } else {
            smsManager.sendTextMessage(phoneNumber, null, content, sentIntent, null);
        }
    }

    /**
     * 获取手机联系人
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>}</p>
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.READ_CONTACTS"/>}</p>
     *
     * @param context 上下文;
     * @return 联系人链表
     */
    public static JSONArray getAllContactInfo(Context context) {
        // 1.获取内容解析者
        ContentResolver resolver = context.getContentResolver();
        // 2.获取内容提供者的地址:com.android.contacts
        // raw_contacts表的地址 :raw_contacts
        // view_data表的地址 : data
        // 3.生成查询地址
        Uri raw_uri = Uri.parse("content://com.android.contacts/raw_contacts");
        // 4.查询操作,先查询raw_contacts,查询contact_id
        // projection : 查询的字段
        String sort = "date desc";
        Cursor cursor = resolver.query(raw_uri, new String[]{"contact_id"}, null, null, null);
        if (cursor == null) {
            return null;
        }
        Uri date_uri = Uri.parse("content://com.android.contacts/data");
        JSONArray list = new JSONArray();

        while (cursor.moveToNext()) {// 5.解析cursor
            String contact_id = cursor.getString(0);
            // cursor.getStringWithBase64(cursor.getColumnIndex("contact_id"));//getColumnIndex
            // : 查询字段在cursor中索引值,一般都是用在查询字段比较多的时候
            // 判断contact_id是否为空
            if (!TextUtils.isEmpty(contact_id)) {
                // 7.根据contact_id查询view_data表中的数据
                // selection : 查询条件
                // selectionArgs :查询条件的参数
                // sortOrder : 排序
                // 空指针: 1.null.方法 2.参数为null
                Cursor c = resolver.query(date_uri, new String[]{"data1", "mimetype"}, "raw_contact_id=?", new String[]{contact_id}, null);
                HashMap<String, String> map = new HashMap<String, String>();
                // 8.解析c
                while (c.moveToNext()) {
                    // 9.获取数据
                    String data1 = c.getString(0);
                    String mimetype = c.getString(1);
                    // 10.根据类型去判断获取的data1数据并保存
                    switch (mimetype) {
                        case "vnd.android.cursor.item/phone_v2": // 电话
                            map.put("phone", data1);
                            break;
                        case "vnd.android.cursor.item/name": // 姓名
                            map.put("name", data1);
                            break;
                    }
                }
                // 11.添加到集合中数据
                if (map.size() > 0) {
                    list.add(map);
                }
                // 12.关闭cursor
                c.close();
            }
        }
        // 12.关闭cursor
        cursor.close();
        return list;
    }

    /**
     * 获取手机短信并保存到xml中
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>}</p>
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.READ_SMS"/>}</p>
     *
     * @param context 上下文
     * @param day
     * @return
     */
    public static JSONArray getSMS(Context context, String range, int day) {
        if (range == null) {
            range = "接收";
        }
        ContentResolver resolver = context.getContentResolver();
        // 获取内容提供者地址   sms,sms表的地址:null  不写
        // 获取查询路径
        Uri uri = null;
        switch (range) {
            case "全部":
                uri = Uri.parse("content://sms");
                break;
            case "发送":
                uri = Uri.parse("content://sms/outbox");
                break;
            default:
            case "接收":
                uri = Uri.parse("content://sms/inbox");
                break;
        }
        if (resolver == null) {
            return new JSONArray();
        }
        //  查询操作
        // projection : 查询的字段
        // selection : 查询的条件
        // selectionArgs : 查询条件的参数
        // sortOrder : 排序
        String selection = null;
        String[] selectionArgs = null;
        if (day > 0) {
            long l = System.currentTimeMillis();
            long yesterday = l - (day * 24 * 60 * 60000);
            selection = "date > ?";
            selectionArgs = new String[]{"" + yesterday};
        }
        Cursor cursor = resolver.query(uri, new String[]{"address", "date", "read", "type", "body"}, selection, selectionArgs, "date desc");
        if (cursor == null) {
            return new JSONArray();
        }
        SimpleDateFormat sdf = XLog.getSafeDateFormat("yyyy-MM-dd HH:mm:ss");
        JSONArray allJson = new JSONArray();
        while (cursor.moveToNext()) {
            JSONObject jsonObject = new JSONObject();
            String address = cursor.getString(0);
            String date = cursor.getString(1);
            int read = cursor.getInt(2);
            String type = cursor.getString(3);
            String body = cursor.getString(4);

            jsonObject.put("address", address);
            jsonObject.put("date", sdf.format(new Date(Long.parseLong(date))));
            jsonObject.put("read", read == 0 ? "未读" : "已读");
            jsonObject.put("type", type);
            jsonObject.put("body", body);

            allJson.add(jsonObject);
        }
        cursor.close();
        return allJson;
    }

    public static Uri writeSMS(Context context, SMSData smsData) {
        ContentResolver cr = context.getContentResolver();
        ContentValues values = new ContentValues();
        //添加短信
        values.put("address", smsData.mAddress);
        values.put("date", smsData.mDate);
        values.put("type", smsData.mType);
        values.put("body", smsData.mBody);
        Uri insert = cr.insert(Uri.parse("content://sms"), values);
        return insert;
    }

    /*
     * @param uri           需要查询的URI，（这个URI是ContentProvider提供的）
     * @param projection    需要查询的字段
     * @param selection     sql语句where之后的语句
     * @param selectionArgs ?占位符代表的数据
     * @param sortOrder     排序方式
     * @return
     */
    public static JSONArray getCallRecord(int day) {
        ContentResolver resolver = XLog.sContext.getContentResolver();

        Uri callUri = CallLog.Calls.CONTENT_URI;
        String[] columns = {CallLog.Calls.CACHED_NAME// 通话记录的联系人
                , CallLog.Calls.NUMBER// 通话记录的电话号码
                , CallLog.Calls.DATE// 通话记录的日期
                , CallLog.Calls.DURATION// 通话时长
                , CallLog.Calls.TYPE};// 通话类型}
        // 查询通话记录的URI
        String selection = null;
        String[] selectionArgs = null;
        if (day > 0) {
            long l = System.currentTimeMillis();
            long yesterday = l - (day * 24 * 60 * 60000);
            selection = "date > ?";
            selectionArgs = new String[]{"" + yesterday};
        }
        String sortOrder = CallLog.Calls.DEFAULT_SORT_ORDER; /* 按照时间逆序排列，最近打的最先显示 */
        Cursor cursor = resolver.query(callUri, columns, selection, selectionArgs, sortOrder);
        SimpleDateFormat sdf = XLog.getSafeDateFormat("yyyy-MM-dd HH:mm:ss");
        JSONArray ja = new JSONArray();
        while (cursor.moveToNext()) {
            String name = cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME));
            String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
            long dateLong = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATE));
            String date = sdf.format(new Date(dateLong));

            int duration = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.DURATION));
            int type = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE));
            String dayCurrent = new SimpleDateFormat("dd").format(new Date());
            String dayRecord = new SimpleDateFormat("dd").format(new Date(dateLong));
            String typeString = "";
            switch (type) {
                case CallLog.Calls.INCOMING_TYPE:
                    typeString = "呼入";
                    break;
                case CallLog.Calls.OUTGOING_TYPE:
                    typeString = "呼出";
                    break;
                case CallLog.Calls.MISSED_TYPE:
                    typeString = "未接";
                    break;
                default:
                    break;
            }
            if (RegexUtils.isMobileSimple(number)) {
                String dayString = "";
                if ((Integer.parseInt(dayCurrent)) == (Integer.parseInt(dayRecord))) {
                    dayString = "今天";
                } else if ((Integer.parseInt(dayCurrent) - 1) == (Integer.parseInt(dayRecord))) {
                    dayString = "昨天";
                } else {
                    dayString = "前天";
                }

                Map<String, String> map = new HashMap<>();
                //"未备注联系人"
                map.put("name", (name == null) ? "未备注" : name);//姓名
                map.put("number", number);//手机号
                map.put("date", date);//通话日期
                map.put("duration", (duration / 60) + "分钟");//时长
                map.put("type", typeString);//类型
                map.put("day", dayString);//

                ja.add(map);
            }
        }
        cursor.close();
        return ja;
    }

    /**
     * 收起状态栏
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>}</p>
     *
     * @param ctx 上下文
     */
    @SuppressLint("WrongConstant")
    public static void collapseStatusBar(Context ctx) {
        Object sbservice = ctx.getSystemService("statusbar");
        try {
            Class<?> statusBarManager = Class.forName("android.app.StatusBarManager");
            Method collapse;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                collapse = statusBarManager.getMethod("collapsePanels");
            } else {
                collapse = statusBarManager.getMethod("collapse");
            }
            collapse.invoke(sbservice);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 展开状态栏
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>}</p>
     *
     * @param ctx 上下文
     */
    @SuppressLint("WrongConstant")
    public static void expandStatusBar(Context ctx) {
        Object sbservice = ctx.getSystemService("statusbar");
        try {
            Class<?> statusBarManager = Class.forName("android.app.StatusBarManager");
            Method expand;
            if (Build.VERSION.SDK_INT >= 17) {
                expand = statusBarManager.getMethod("expandNotificationsPanel");
            } else {
                expand = statusBarManager.getMethod("expand");
            }
            expand.setAccessible(true);
            expand.invoke(sbservice);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @SuppressLint("WrongConstant")
    public static void disableStatusBar(Context context) {
        Object statusbar = context.getSystemService("statusbar");
        try {
            Class<?> statusBarManager = Class.forName("android.app.StatusBarManager");
            Method disable = HookUtils.getDeclaredMethod(statusBarManager, "disable", int.class);
            disable.setAccessible(true);
            disable.invoke(statusbar, 0x00010000);
        } catch (Exception e) {
            XLog.w(Log.getStackTraceString(e));
        }
    }

    @SuppressLint("WrongConstant")
    public static void enableExpand(Context context) {
        Object statusbar = context.getSystemService("statusbar");
        try {
            Class<?> statusBarManager = Class.forName("android.app.StatusBarManager");
            Method expand = statusBarManager.getMethod("disable", int.class);
            expand.invoke(statusbar, 0x00000000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static class SMSData implements Serializable {
        /**
         * 号码
         */
        private String mAddress;
        /**
         * 日期
         */
        private long mDate;
        /**
         * type 类型
         * ALL    = 0;
         * INBOX  = 1;
         * SENT   = 2;
         * DRAFT  = 3;
         * OUTBOX = 4;
         * FAILED = 5;
         * QUEUED = 6;
         */
        private int mType;
        /**
         * 内容
         */
        private String mBody;

        public SMSData(String address, long date, int type, String body) {
            mAddress = address;
            mDate = date;
            mType = type;
            mBody = body;
        }

        public String getAddress() {
            return mAddress;
        }

        public void setAddress(String address) {
            mAddress = address;
        }

        public long getDate() {
            return mDate;
        }

        public void setDate(long date) {
            mDate = date;
        }

        public int getType() {
            return mType;
        }

        public void setType(int type) {
            mType = type;
        }

        public String getBody() {
            return mBody;
        }

        public void setBody(String body) {
            mBody = body;
        }

        @Override
        public String toString() {
            return "SMSData{" +
                    "date='" + mDate + '\'' +
                    ", address='" + mAddress + '\'' +
                    ", type='" + mType + '\'' +
                    ", body='" + mBody + '\'' +
                    '}';
        }
    }

    /**
     * 生成一个UUID存储下来并返回，下次获取时，如果数据没有被清，则获取到的是同一个值
     *
     * @return uuid
     */
    private static String sUUID;
    private static String FILE_NAME_UUID = ".uu.id";
    private static String KEY_UUID = "uuid";

    public static String getUniqueId() {
        if (!TextUtils.isEmpty(sUUID)) {
            return sUUID;
        }
        String path = Environment.getExternalStorageDirectory().getAbsolutePath();
        File file = new File(path, FILE_NAME_UUID);

        SharedPreferences sp = SPUtils.getSP();
        sUUID = sp.getString(KEY_UUID, null);
        if (!TextUtils.isEmpty(sUUID)) {
            XLog.i("SP.UUID = " + sUUID);
            FileUtils.writeFileFromString(file, sUUID, false);
            return sUUID;
        }

        sUUID = FileUtils.readFile2String(file, "UTF-8");
        if (!TextUtils.isEmpty(sUUID)) {
            XLog.i("File.UUID = " + sUUID);
            sp.edit().putString(KEY_UUID, sUUID).apply();
            return sUUID;
        }
        sUUID = PhoneUtils.getIMEI(XLog.sContext);
        XLog.i("IMEI.UUID->" + sUUID);

        if (TextUtils.isEmpty(sUUID)) {
            sUUID = UUID.randomUUID().toString();
            XLog.i("Random.UUID = " + sUUID);
        }
        sp.edit().putString(KEY_UUID, sUUID).apply();
        FileUtils.writeFileFromString(file, sUUID, false);
        return sUUID;
    }
}